﻿
using Opc.Ua;
using Opc.Ua.Client;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
namespace hconnect {
    public class OPCTcpConnect :OpcUaClient {
        #region Node Write/Read Support
        /// <summary>
        /// Read a value node from server
        /// </summary>
        /// <param name="nodeId">node id</param>
        /// <returns>DataValue</returns>
        public DataValue ReadNode(NodeId nodeId) {
            ReadValueIdCollection nodesToRead = new ReadValueIdCollection
            {
                new ReadValueId( )
                {
                    NodeId = nodeId,
                    AttributeId = Attributes.Value
                }
            };
            if( m_session == null ) {
                return null;
            }
            // read the current value
            m_session.Read(
                null ,
                0 ,
                TimestampsToReturn.Neither ,
                nodesToRead ,
                out DataValueCollection results ,
                out DiagnosticInfoCollection diagnosticInfos);
            ClientBase.ValidateResponse(results ,nodesToRead);
            ClientBase.ValidateDiagnosticInfos(diagnosticInfos ,nodesToRead);
            return results[0];
        }
        /// <summary>
        /// Read a value node from server
        /// </summary>
        /// <typeparam name="T">type of value</typeparam>
        /// <param name="tag">node id</param>
        /// <returns>实际值</returns>

        /// <summary>
        /// read several value nodes from server
        /// </summary>
        /// <param name="nodeIds">all NodeIds</param>
        /// <returns>all values</returns>
        public List<DataValue> ReadNodes(NodeId[] nodeIds) {
            ReadValueIdCollection nodesToRead = new ReadValueIdCollection();
            for( int i = 0;i < nodeIds.Length;i++ ) {
                nodesToRead.Add(new ReadValueId() {
                    NodeId = nodeIds[i] ,
                    AttributeId = Attributes.Value
                });
            }
            // 读取当前的值
            m_session.Read(
                null ,
                0 ,
                TimestampsToReturn.Neither ,
                nodesToRead ,
                out DataValueCollection results ,
                out DiagnosticInfoCollection diagnosticInfos);
            ClientBase.ValidateResponse(results ,nodesToRead);
            ClientBase.ValidateDiagnosticInfos(diagnosticInfos ,nodesToRead);
            return results.ToList();
        }
        /// <summary>
        /// write a note to server(you should use try catch)
        /// </summary>
        /// <typeparam name="T">The type of tag to write on</typeparam>
        /// <param name="tag">节点名称</param>
        /// <param name="value">值</param>
        /// <returns>if success True,otherwise False</returns>
        public bool WriteNode<T>(string tag ,T value) {
            WriteValue valueToWrite = new WriteValue() {
                NodeId = new NodeId(tag) ,
                AttributeId = Attributes.Value
            };
            valueToWrite.Value.Value = value;
            valueToWrite.Value.StatusCode = StatusCodes.Good;
            valueToWrite.Value.ServerTimestamp = DateTime.MinValue;
            valueToWrite.Value.SourceTimestamp = DateTime.MinValue;
            WriteValueCollection valuesToWrite = new WriteValueCollection
           {
                valueToWrite
            };
            // 写入当前的值
            m_session.Write(
               null ,
               valuesToWrite ,
               out StatusCodeCollection results ,
               out DiagnosticInfoCollection diagnosticInfos);
            ClientBase.ValidateResponse(results ,valuesToWrite);
            ClientBase.ValidateDiagnosticInfos(diagnosticInfos ,valuesToWrite);
            if( StatusCode.IsBad(results[0]) ) {
                throw new ServiceResultException(results[0]);
            }
            return !StatusCode.IsBad(results[0]);
        }
        /// <summary>
        /// 所有的节点都写入成功，返回<c>True</c>，否则返回<c>False</c>
        /// </summary>
        /// <param name="tags">节点名称数组</param>
        /// <param name="values">节点的值数据</param>
        /// <returns>所有的是否都写入成功</returns>
        public bool WriteNodes(string[] tags ,object[] values) {
            WriteValueCollection valuesToWrite = new WriteValueCollection();
            for( int i = 0;i < tags.Length;i++ ) {
                if( i < values.Length ) {
                    WriteValue valueToWrite = new WriteValue() {
                        NodeId = new NodeId(tags[i]) ,
                        AttributeId = Attributes.Value
                    };
                    valueToWrite.Value.Value = values[i];
                    valueToWrite.Value.StatusCode = StatusCodes.Good;
                    valueToWrite.Value.ServerTimestamp = DateTime.MinValue;
                    valueToWrite.Value.SourceTimestamp = DateTime.MinValue;
                    valuesToWrite.Add(valueToWrite);
                }
            }
            // 写入当前的值
            m_session.Write(
               null ,
               valuesToWrite ,
               out StatusCodeCollection results ,
               out DiagnosticInfoCollection diagnosticInfos);
            ClientBase.ValidateResponse(results ,valuesToWrite);
            ClientBase.ValidateDiagnosticInfos(diagnosticInfos ,valuesToWrite);
            bool result = true;
            foreach( var r in results ) {
                if( StatusCode.IsBad(r) ) {
                    result = false;
                    break;
                }
            }
            return result;
        }
        #endregion
    }
}
